package com.ruanxie.config;

import com.ruanxie.constant.WebDriverConstant;
import com.ruanxie.interceptor.JwtTokenUserInterceptor;
import com.ruanxie.properties.WebDriverProperties;
import lombok.extern.slf4j.Slf4j;
import net.lightbody.bmp.BrowserMobProxy;
import net.lightbody.bmp.BrowserMobProxyServer;
import net.lightbody.bmp.client.ClientUtil;
import net.lightbody.bmp.proxy.CaptureType;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.openqa.selenium.Proxy;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.remote.CapabilityType;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.config.annotation.*;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.IOException;

/**
 * 配置类：配置项目，注册web层相关组件
 */
@Configuration
@Slf4j
public class WebMvcConfiguration extends WebMvcConfigurationSupport {
    @Autowired
    private JwtTokenUserInterceptor jwtTokenUserInterceptor;


    //TODO 尝试：优化：使用Spring Security来进行角色验证
        //（目前还没学，先用最简单的方式了）
    /**
     * 注册自定义拦截器
     * @param registry
     */
    protected void addInterceptors(InterceptorRegistry registry){
        log.info("注册自定义拦截器...");
        registry.addInterceptor(jwtTokenUserInterceptor)
                .addPathPatterns("/api/student/**")
                .addPathPatterns("/api/teaching/**");
    }

    /**
     * 通过knife4j生成接口文档
     * @return
     */
    @Bean
    public Docket docket() {
        log.info("准备接口文档...");
        ApiInfo apiInfo = new ApiInfoBuilder()
                .title("大创项目接口文档")
                .version("2.0")
                .description("大创项目接口文档")
                .build();
        Docket docket = new Docket(DocumentationType.SWAGGER_2)
                .apiInfo(apiInfo)
                .select()
                .apis(RequestHandlerSelectors.basePackage("com.ruanxie.controller"))
                .paths(PathSelectors.any())
                .build();
        return docket;
    }

    /**
     * 设置静态资源映射
     * @param registry
     * 访问地址：localhost:端口号/doc.html
     */
    protected void addResourceHandlers(ResourceHandlerRegistry registry) {
        log.info("开始设置静态资源映射...");
        registry.addResourceHandler("/doc.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/");
    }

    //selenium和proxy相关IOC容器

    /**
     * 配置抓包初始化工具
     * @return
     */
    @Bean
    public BrowserMobProxy browserMobProxy(){
        //创建BrowserMob Proxy抓包工具实例
        BrowserMobProxy browserMobProxy=new BrowserMobProxyServer();
        browserMobProxy.start();//这里会运行在一个随机的端口
        browserMobProxy.setHarCaptureTypes(CaptureType.RESPONSE_CONTENT);
        browserMobProxy.enableHarCaptureTypes(CaptureType.RESPONSE_BINARY_CONTENT);
        //配置代理浏览器
        //在Selenium中，所需的能力是一种可选配置选项，用于自定义和控制不同浏览器的行为。
                /*一堆我还没有接触到的功能：随便举几个感兴趣的：
                    1.网络请求、
                    2.IP伪装和地理位置模拟
                    还有一堆*/
        return browserMobProxy;
    }

    /**
     * 配置浏览器选项（这里带上了抓包）
     * @param browserMobProxy
     * @return
     */
    @Bean
    public ChromeOptions chromeOptions(BrowserMobProxy browserMobProxy) throws IOException {
        //创建一个Selenium代理对象，这个proxy能够定义端口
        Proxy seleniumProxy= ClientUtil.createSeleniumProxy(browserMobProxy);//别导错包
        browserMobProxy.newHar();//用来记录代理过后的请求和响应
        //配置浏览器选项
        ChromeOptions chromeOptions=new ChromeOptions();
        chromeOptions.addArguments("--remote-allow-origins=*");
        //优化一下
        //TODO 不在打开渲染浏览器，测试时可以启动
//        chromeOptions.addArguments("--headless"); // 无头模式:不需要渲染图形界面。
//        chromeOptions.addArguments("--disable-gpu"); // 禁用 GPU 加速:提高兼容性和稳定性，特别是在不支持 GPU 加速的环境中。
//        chromeOptions.addArguments("--no-sandbox"); // 禁用沙盒:解决权限问题，提高兼容性，但要注意安全性。
//        chromeOptions.addArguments("--incognito");//无痕模式

        chromeOptions.setProxy(seleniumProxy);
        chromeOptions.setAcceptInsecureCerts(true);

        return chromeOptions;
    }
    @Autowired
    private ResourceLoader resourceLoader;
    @Autowired
    private WebDriverProperties webDriverProperties;

    /**
     * 设置环境变量（一开始放在下面，放这里的原因是因为只需要一次，为什么这样设置具体看下面注释）
     * @throws IOException
     */
    @PostConstruct
    public void setWebDriverPath() throws IOException {
        //浏览器内核（谷歌,edge,火狐）
        //这里因为有多个浏览器，这里就用edge了,理论上是可以配置多个的
        //DONE 待做：放入配置文件中

        // 加载资源文件
        org.springframework.core.io.Resource resource = resourceLoader.getResource(webDriverProperties.getChrome().getDriverPath());
        String chromeDriverPath = resource.getFile().getAbsolutePath();
//        log.info(chromeDriverPath);
//        String browserURL="C:\\Users\\wuyihan\\Desktop\\current_project\\LeaningSystem\\LeaningSystem-bakend\\intelligent-learning-situation-analysis\\intelligent-server\\src\\main\\resources\\chromedriver-win64\\chromedriver.exe";
        // 设置 Microsoft Edge WebDriver 的路径（环境变量中）
        String browserDriver= WebDriverConstant.WEBDRIVER_CHROME_DRIVER;
        System.setProperty(browserDriver,chromeDriverPath);

        //配置下edge的
        browserDriver=WebDriverConstant.WEBDRIVER_EDGE_DRIVER;
        resource=resourceLoader.getResource(webDriverProperties.getEdge().getDriverPath());
        String edgeDriverPath=resource.getFile().getAbsolutePath();
        System.setProperty(browserDriver,edgeDriverPath);
    }


    //TODO 尝试：优化：使用下线程池技术
    /**
     * 开启一个浏览器对象(还是觉得放在线程池或者连接池中好点
     * (能搞，但是目前就先弄一个)
     * @param chromeOptions
     * @return
     * @throws IOException
     */
    @Bean
    public WebDriver webDriver(ChromeOptions chromeOptions) throws IOException {
        //开启一个浏览器对象
        //TODO 选择：下面这条语句是谷歌的，感觉可以通过简单工厂再配置文件中选择
        //          如果使用的是edge代码还没完成完善好
        WebDriver webDriver=new ChromeDriver(chromeOptions);

        //服啦，用edge更快
        //        System.setProperty("webdriver.edge.driver","C:\\Users\\wuyihan\\Desktop\\current_project\\LeaningSystem\\LeaningSystem-bakend\\intelligent-learning-situation-analysis\\intelligent-server\\src\\main\\resources\\chromedriver-win64\\chromedriver.exe");
//        WebDriver webDriver=new EdgeDriver(chromeOptions);
        return webDriver;
    }

//    /**
//     * 根据浏览器配置选项
//     * （这里其实每次都new最好，这样能够生成多个浏览器页面，但是这里还没有这个需求，直接就至始至终用一个了）
//     * 下面那些注释是失败代码，方便以后复现
//     * 解决：相对路径出现问题，与mybatis框架一样，直接使用resource文件，避开相对路径
//     * @param chromeOptions
//     * @return
//     */
//    @Autowired
//    private ResourceLoader resourceLoader;
//    @Autowired
//    private ChromeDriverProperties chromeDriverProperties;
//    @Bean
////    @Scope("prototype")
////    public void init() throws IOException {//需要其他的bean对象依赖，直接作为形参传入
//    public WebDriver webDriver(ChromeOptions chromeOptions) throws IOException {
//        //浏览器内核（谷歌,edge,火狐）
//            //这里因为有多个浏览器，这里就用edge了,理论上是可以配置多个的
//        //DONE 待做：放入配置文件中
//        String browserDriver= WebDriverConstant.WEBDRIVER_CHROME_DRIVER;
//        // 加载资源文件
//        org.springframework.core.io.Resource resource = resourceLoader.getResource(chromeDriverProperties.getDriverPath());
//        String chromeDriverPath = resource.getFile().getAbsolutePath();
////        String browserURL="C:\\Users\\wuyihan\\Desktop\\current_project\\LeaningSystem\\LeaningSystem-bakend\\intelligent-learning-situation-analysis\\intelligent-server\\src\\main\\resources\\chromedriver-win64\\chromedriver.exe";
//        // 设置 Microsoft Edge WebDriver 的路径（环境变量中）
//        System.setProperty(browserDriver,chromeDriverPath);
//
//        //开启一个浏览器对象
//        WebDriver webDriver=new ChromeDriver(chromeOptions);
//        return webDriver;
//    }
////    /**
////     * 失败代码：主要是相对路径的问题，不知道为什么用启动项时，就跑到项目的项目的最外层LeaningSystem-bakend里面?
////     * @param chromeOptions
////     * @return
////     * @throws IOException
////     */
////    @Bean
////    public WebDriver webDriver(ChromeOptions chromeOptions) throws IOException {//需要其他的bean对象依赖，直接作为形参传入
////
////        //浏览器内核（谷歌,edge,火狐）
////        //这里因为有多个浏览器，这里就用edge了,理论上是可以配置多个的
////        String browserDriver="webdriver.chrome.driver";
////        String browserURL="src/main/resources/chromedriver-win64/chromedriver.exe";
//////        String browserURL="intelligent-learning-situation-analysis/intelligent-server/src/main/resources/chromedriver-win64/chromedriver.exe";
////        // 加载资源文件
//////        org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:chromedriver-win64/chromedriver.exe");
////
//////        String chromeDriverPath = resource.getFile().getAbsolutePath();
////
//////        String browserURL="C:\\Users\\wuyihan\\Desktop\\current_project\\LeaningSystem\\LeaningSystem-bakend\\intelligent-learning-situation-analysis\\intelligent-server\\src\\main\\resources\\chromedriver-win64\\chromedriver.exe";
////        // 设置 Microsoft Edge WebDriver 的路径（环境变量中）
////        System.setProperty(browserDriver,browserURL);
//////        System.setProperty(browserDriver,chromeDriverPath);
////
////        //开启一个浏览器对象
////        WebDriver webDriver=new ChromeDriver(chromeOptions);
////        return webDriver;
////    }





    //获取河北经贸大学的https数据

    /**
     * 用来发送网络请求
     * 注意事项：用完必须释放连接
     * @return
     */
    @Bean
    public CloseableHttpClient closeableHttpClient(){
        return HttpClients.createDefault();
    }


}
